﻿using Microsoft.AspNetCore.Http;
using mozhi.smarterp.Finance.Accounts;
using mozhi.smarterp.Finance.Accounts.Repository;
using mozhi.smarterp.Finance.Enums;
using mozhi.smarterp.Finance.Querys;
using Mozhi.Abp.Core.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace mozhi.smarterp.Finance.Finances.Services.EndPeriodProcess
{
    /// <summary>
    /// 摊销长期待摊费用
    /// </summary>
    public class AmortizeExpensesEndPeriodProcessor : EndPeriodProcessorBase<AccountBalance>
    {
        /// <summary>
        /// 上一期余额
        /// </summary>
        private List<AccountBalance> _previousPeriodBalances;

        public AmortizeExpensesEndPeriodProcessor(EndPeriodProcessItem item, int period, IServiceProvider serviceProvider) : base(item, period, serviceProvider)
        {
        }

        protected override async Task LoadCalculationDataAsync()
        {
            await base.LoadCalculationDataAsync();

            var accountBalanceRepository = _serviceProvider.GetService(typeof(IAccountBalanceRepository)) as IAccountBalanceRepository;

            _previousPeriodBalances = await accountBalanceRepository.FindAsync(new AccountBalanceQuery() { Period = _period.ToPrePeriod(), IncludeCurrency = false, IncludeDimension = false });
        }

        /// <summary>
        /// 进行数据处理
        //1.金额默认取0
        //2.如果上期有做过此凭证，则取上期长期待摊费用贷方
        //3.如果本期有做过长期待摊费用科目的凭证，则取此科目的贷方
        /// </summary>
        /// <returns></returns>
        protected override async Task<EndPeriodProcessResult> HandleDataAsync()
        {
            EndPeriodProcessResult result = null;

            //取综合本位币金额
            _data = _data.Where(x => x.CurrencyId == null && x.DimensionGroupValueId == null).ToList();

            ///长期摊销待摊费用
            var account660207 = GetFirstLeafAccount(GetEndPeriodProcessSettingAsync("660207")?.CustomAccountCode);

            //长期待摊费用
            var account1801 = GetFirstLeafAccount(GetEndPeriodProcessSettingAsync("1801")?.CustomAccountCode);

            //长期摊销待摊费用余额
            var balances1801 = _data.Where(x => x.AccountId == account1801.Id).ToList();


            //上一期摊销费用
            var previousPeriodBalances660207 = _previousPeriodBalances.Where(x => x.AccountId == account660207.Id && x.CurrencyId == null && x.DimensionGroupValueId == null).ToList();

            var previousPeriod660207DebitAmount = previousPeriodBalances660207.Where(x=>x.DebitAmount.HasValue).Sum(x => x.DebitAmount);

            previousPeriod660207DebitAmount = previousPeriod660207DebitAmount == null ? 0.00M : previousPeriod660207DebitAmount.Value;

            //待摊费用余额
            var balances1801ClosingAmount = balances1801.Where(x=>x.ClosingAmount.HasValue).Sum(x => x.ClosingAmount);

            balances1801ClosingAmount = balances1801ClosingAmount == null ? 0.00M : balances1801ClosingAmount.Value;

            //测算金额   //如果上期摊销大于余额就取余额，如果上期摊销为0 则取余额，如果上期摊销在0 和余额之间就取上期摊销
            var amount = (previousPeriod660207DebitAmount.Value > 0 && previousPeriod660207DebitAmount.Value <= balances1801ClosingAmount.Value) ? previousPeriod660207DebitAmount.Value : balances1801ClosingAmount.Value;

            result = new EndPeriodProcessResult(_guidGenerator.Create(), _item.Id, _period, Enums.EndPeriodProcessType.AmortizationExpense);

            var items = GetResultItems(result.Id, balances1801ClosingAmount.Value, previousPeriod660207DebitAmount.Value);

            foreach (var item in items)
            {
                result.AddItem(item);
            }

            return result;
        }

        protected override async Task<Journal> HandleGenerateJournalAsync()
        {
            _data = _data.Where(x => x.DimensionGroupValueId != null && x.CurrencyId != null).ToList();

            //取综合本位币金额
            _data = _data.Where(x => x.CurrencyId == null && x.DimensionGroupValueId == null).ToList();

            ///长期摊销待摊费用
            var account660207 = GetFirstLeafAccount(GetEndPeriodProcessSettingAsync("660207")?.CustomAccountCode);

            //长期待摊费用
            var account1801 = GetFirstLeafAccount(GetEndPeriodProcessSettingAsync("1801")?.CustomAccountCode);

            var measureResult = await GetEndPeriodResultAsync();

            var account660207Amount = measureResult?.MeasureValue;

            var journalMananger = _serviceProvider.GetService(typeof(JournalManager)) as JournalManager;

            //按照核算维度进行结转

            var defaultJournalNumberPrefix = await GetJournalDefaultNumberPrefix();

            var journal = await journalMananger.Create(_guidGenerator.Create(), defaultJournalNumberPrefix.Id, _period.ToLastDayDateTime());

            var journalItemDebit = await GetJournalItemAsync("摊销长期待摊费用", account660207Amount ?? 0, account660207, null, 0, AccountDirectionType.Debit);

            var journalItemCreadit = await GetJournalItemAsync("摊销长期待摊费用", account660207Amount ?? 0, account1801, null, 1, AccountDirectionType.Credit);

            journal.ChangeItems(new List<JournalItem>() { journalItemDebit, journalItemCreadit });

            return journal;
        }

        #region
        private List<EndPeriodProcessResultItem> GetResultItems(Guid resultId, decimal balances660207Amount, decimal previousPeriod1801Amount)
        {
            var result = new List<EndPeriodProcessResultItem>();

            result.Add(new EndPeriodProcessResultItem(_guidGenerator.Create(), resultId, "长期待摊费用余额", balances660207Amount.ToString(), 1, 1, false));

            result.Add(new EndPeriodProcessResultItem(_guidGenerator.Create(), resultId, "上期摊销费用", previousPeriod1801Amount.ToString(), 1, 2, false));

            return result;
        }
        #endregion
    }
}
